import request from '@/utils/request.js' // 你的axios封装

let controller
let failTimes = 0
const retryTimes = 3

/**
 * @return {promise}
 */
const upload = ({
  file, // 用户选择的二进制文件

  fileType, // 当前实例的文件类型

  /**
   * json转FormData
   *
   * @param {json} param - 参数
   * @return {formData} formData格式的参数
   */
  jsonToFormData,

  /**
   * 设置上传进度
   *
   * @param {number} progress - 进度 范围[0, 1]
   */
  setProgress,

  /**
   * 切割文件（分片上传时有用）
   *
   * @param {file} file - 二进制文件
   * @param {number} chunkSize - 分片大小 单位字节 默认10M
   * @return {array} 文件分片
   */
  sliceFile,

  MB,
  GB // 文件容量单位 方便用于chunkSize参数
}) => {
  const chunkSize = 10 * MB

  failTimes = 0
  controller = new AbortController()

  const chunks = sliceFile(file, chunkSize)
  let count = 0

  const formData = jsonToFormData({
    dir: fileType,
    chunkTotal: chunks.length.toString(),
    fileName: file.name,
    domainId: import.meta.env.VITE_APP_domainId,
  })

  return new Promise((resolve, reject) => {
    function recursion () {
      formData.set('file', chunks[count])
      formData.set('chunk', count.toString())
      formData.set('domainId', import.meta.env.VITE_APP_domainId)
      request({
        baseURL: '',
        url: import.meta.env.VITE_APP_UPLOAD_API + 'chunkUpload',
        method: 'POST',
        data: formData,
        timeout: 0,
        onUploadProgress (progressEvent) {
          const pct = (chunkSize * count + progressEvent.loaded) / file.size
          setProgress(pct >= 1 ? 0.99 : pct)
        },
        signal: controller.signal,
      })
        .then(res => {
          const data = 'data' in res ? res.data : res
          if (data?.status === '200') {
            setProgress(1)
            resolve(data.url)
          } else if (count++ < chunks.length - 1) {
            formData.set('taskId', data.url)
            recursion()
          } else {
            setProgress(1)
            reject('上传失败')
          }
        })
        .catch(({ message }) => {
          // 断点续传
          if (failTimes++ < retryTimes) {
            recursion()
          } else if (message === 'canceled') {
            reject('上传取消')
          } else {
            reject('上传失败')
          }
        })
    }

    recursion()
  })
}

const onAbort = () => {
  // 在上传中途点击取消按钮触发
  // 可以在这里重置断点续传次数、中止请求、调接口清除分片文件等
  failTimes = Number.MAX_VALUE
  controller?.abort()
}

export { upload, onAbort }
